package com.relytosoft.mizar.analyze.face.services.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.relytosoft.dubhe.common.core.base.page.PageQuery;
import com.relytosoft.dubhe.common.core.exception.ServiceException;
import com.relytosoft.dubhe.common.elasticsearch.ElasticsearchUtil;
import com.relytosoft.dubhe.common.elasticsearch.page.PageResult;
import com.relytosoft.mizar.analyze.base.entity.pojo.dto.TaskRequestDto;
import com.relytosoft.mizar.analyze.base.enums.DeleteStatusEnum;
import com.relytosoft.mizar.analyze.base.enums.IndexNameTypeEnum;
import com.relytosoft.mizar.analyze.base.enums.TaskStatusEnum;
import com.relytosoft.mizar.analyze.common.utils.IndexUtil;
import com.relytosoft.mizar.analyze.face.api.entity.AyFaceTask;
import com.relytosoft.mizar.analyze.face.api.entity.AyFaceTaskSon;
import com.relytosoft.mizar.analyze.face.api.pojo.dto.AyFaceTaskDto;
import com.relytosoft.mizar.analyze.face.api.pojo.dto.AyFaceTaskUpdateDto;
import com.relytosoft.mizar.analyze.face.api.pojo.dto.AyTaskIdDto;
import com.relytosoft.mizar.analyze.face.api.pojo.query.AyFaceTaskQuery;
import com.relytosoft.mizar.analyze.face.api.pojo.query.AyFaceTaskSearchQuery;
import com.relytosoft.mizar.analyze.face.api.pojo.vo.AyBatchVo;
import com.relytosoft.mizar.analyze.face.api.pojo.vo.AyCameraVo;
import com.relytosoft.mizar.analyze.face.api.pojo.vo.AyFaceTaskVo;
import com.relytosoft.mizar.analyze.face.services.mapper.AyFaceTaskMapper;
import com.relytosoft.mizar.analyze.face.services.mapper.AyFaceTaskSonMapper;
import com.relytosoft.mizar.analyze.face.services.service.AyFaceTaskService;
import com.relytosoft.mizar.analyze.face.services.service.AyFaceTaskSonService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lj
 * @date 2022/5/16 11:34
 */
@Service
public class AyFaceTaskServiceImpl extends ServiceImpl<AyFaceTaskMapper, AyFaceTask> implements AyFaceTaskService {


    @Resource
    private AyFaceTaskMapper ayFaceTaskMapper;

    @Resource
    private AyFaceTaskSonMapper ayFaceTaskSonMapper;

    @Resource
    private AyFaceTaskSonService ayFaceTaskSonService;

    @Resource
    private ElasticsearchUtil elasticsearchUtil;


    @Override
    public IPage<AyFaceTaskVo> selectAyFaceTaskPageList(PageQuery pageQuery, AyFaceTaskQuery ayFaceTaskQuery) {
        if (StrUtil.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("id");
            pageQuery.setIsAsc("desc");
        }
        return ayFaceTaskMapper.selectPageTaskList(pageQuery.build(), ayFaceTaskQuery);
    }

    @Override
    public boolean updateAyFaceTask(AyFaceTaskUpdateDto ayFaceTaskUpdateDto) {
        if (null != ayFaceTaskUpdateDto) {
            ayFaceTaskMapper.updateFaceTask(ayFaceTaskUpdateDto);
            return true;
        }
        throw new ServiceException("不存在的任务");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<TaskRequestDto> insertTaskWithSonWith(AyFaceTaskDto ayFaceTaskDto, AyFaceTask ayFaceTask) {
        boolean save = this.save(ayFaceTask);
        ArrayList<TaskRequestDto> taskRequestDtoS = new ArrayList<>();
        if (save) {
            for (AyCameraVo cameraVo : ayFaceTaskDto.getAyCameraVos()) {
                AyFaceTaskSon ayFaceTaskSon = new AyFaceTaskSon();
                ayFaceTaskSon.setCameraId(cameraVo.getCameraId());
                ayFaceTaskSon.setCameraName(cameraVo.getCameraName());
                ayFaceTaskSon.setVideoUrl(cameraVo.getVideoUrl());
                ayFaceTaskSon.setFaceTaskId(ayFaceTask.getId());
                ayFaceTaskSon.setTaskName(ayFaceTask.getName());
                ayFaceTaskSon.setStatus(ayFaceTask.getStatus());
                boolean saveSon = ayFaceTaskSonService.insertAyFaceTaskSon(ayFaceTaskSon);
                if (saveSon && TaskStatusEnum.CREATED.getValue() == ayFaceTask.getStatus()) {
                    taskRequestDtoS.add(ayFaceTaskSonService.createRequest(ayFaceTaskSon));
                    continue;
                }
            }
            return taskRequestDtoS;
        }
        throw new ServiceException("创建人脸任务失败");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<TaskRequestDto> startAyFaceTask(AyTaskIdDto ayTaskIdDto, AyFaceTask ayFaceTask, List<AyFaceTaskSon> ayFaceTaskSons) {
        ayFaceTask.setStatus(TaskStatusEnum.RUNING.getValue());
        ayFaceTask.setUpdatedBy(ayTaskIdDto.getUpdatedBy());
        ayFaceTask.setUpdatedId(ayTaskIdDto.getUpdatedId());
        ayFaceTask.setBeginTime(LocalDateTime.now());
        ayFaceTask.setEndTime(null);
        boolean update = this.updateById(ayFaceTask);
        ArrayList<TaskRequestDto> taskRequestDtoS = new ArrayList<>();
        if (update) {
            for (AyFaceTaskSon taskSon : ayFaceTaskSons) {
                boolean startSon = ayFaceTaskSonService.startAyFaceTaskSon(ayTaskIdDto, taskSon);
                if (startSon) {
                    taskRequestDtoS.add(ayFaceTaskSonService.createRequest(taskSon));
                    continue;
                }
            }
            return taskRequestDtoS;
        }
        throw new ServiceException("启动人脸分析任务失败");
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<String> stopAyFaceTask(AyTaskIdDto ayTaskIdDto, AyFaceTask ayFaceTask, List<AyFaceTaskSon> ayFaceTaskSons) {
        ayFaceTask.setStatus(TaskStatusEnum.FINISHED.getValue());
        ayFaceTask.setUpdatedBy(ayTaskIdDto.getUpdatedBy());
        ayFaceTask.setUpdatedId(ayTaskIdDto.getUpdatedId());
        ayFaceTask.setEndTime(LocalDateTime.now());
        boolean update = this.updateById(ayFaceTask);
        List<String> taskIds = new ArrayList<>();
        if (update) {
            for (AyFaceTaskSon taskSon : ayFaceTaskSons) {
                boolean stopSon = ayFaceTaskSonService.stopAyFaceTaskSon(ayTaskIdDto, taskSon);
                if (stopSon) {
                    taskIds.add(taskSon.getTaskId());
                    continue;
                }
            }
            return taskIds;
        }
        throw new ServiceException("停止人脸分析任务失败");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteTaskWithSonWith(AyTaskIdDto ayTaskIdDto) {
        int updatedId = ayTaskIdDto.getUpdatedId();
        String updatedBy = ayTaskIdDto.getUpdatedBy();
        List<Integer> ids = ayTaskIdDto.getIds();

        for (Integer id : ids) {
            AyFaceTask task = getById(id);
            task.setUpdatedBy(updatedBy);
            task.setUpdatedId(updatedId);
            task.setIsDeleted(DeleteStatusEnum.DELETED.getValue());
            if (updateById(task)) {
                List<Integer> sonIds = ayFaceTaskSonMapper.selectSonIds(task.getId());
                ayTaskIdDto.setIds(sonIds);
                ayFaceTaskSonService.updateAyFaceTaskSon(ayTaskIdDto);
            }
        }
    }


    @Override
    public AyBatchVo insertTaskByDto(AyFaceTaskDto ayFaceTaskDto) {
        //所有需要添加的设备id
        List<AyCameraVo> ayCameraVos = ayFaceTaskDto.getAyCameraVos();

        AyBatchVo ayBatchVo = new AyBatchVo();
        ayBatchVo.setTotal(ayCameraVos.size());
        //没有符合条件的设备
        if (addFrontVerify(ayFaceTaskDto)) {
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ayCameraVos.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("没有符合创建条件的设备"));
            return ayBatchVo;
        }
        AyFaceTask ayFaceTask = AyFaceTaskDto.buildAddTask(ayFaceTaskDto);
        List<TaskRequestDto> taskRequestDtoS = insertTaskWithSonWith(ayFaceTaskDto, ayFaceTask);
        taskRequestDtoS.stream().forEach(a -> ayFaceTaskSonService.insertFaceTaskSonKafkaOpMsg(a));

        ayBatchVo.setSuccess(taskRequestDtoS.size());
        ayBatchVo.setError(ayCameraVos.size() - taskRequestDtoS.size());
        ayBatchVo.setErrorMsg(Collections.singletonList("符合条件的任务已添加成功"));

        return ayBatchVo;
    }

    /**
     * 人脸任务添加前置验证
     *
     * @param ayFaceTaskDto
     * @return
     */
    public Boolean addFrontVerify(AyFaceTaskDto ayFaceTaskDto) {
        Integer id = ayFaceTaskMapper.selectFaceTaskId(ayFaceTaskDto.getName());
        if (null != id) {
            throw new ServiceException("创建任务发生错误：任务名已存在");
        }
        List<AyCameraVo> ayCameraVos = ayFaceTaskDto.getAyCameraVos();
        //所有需要添加的设备ids
        if (ayCameraVos.isEmpty()) {
            return false;
        }
        Iterator<AyCameraVo> cameraVoIterator = ayCameraVos.iterator();
        while (cameraVoIterator.hasNext()) {
            AyCameraVo cameraVo = cameraVoIterator.next();
            List<AyFaceTaskSon> taskSons = ayFaceTaskSonService.list(new LambdaQueryWrapper<AyFaceTaskSon>()
                    .eq(AyFaceTaskSon::getCameraId, cameraVo.getCameraId())
                    .eq(AyFaceTaskSon::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue()));
            if (!taskSons.isEmpty()) {
                //过滤已经存在的camera
                cameraVoIterator.remove();
            }
        }
        return ayCameraVos.isEmpty();
    }

    /**
     * 人脸任务删除前置验证
     *
     * @param ids 主任务集合
     * @return
     */
    public Boolean deleteTaskFrontVerify(List<Integer> ids) {
        if (ids.isEmpty()) {
            return false;
        }
        Iterator<Integer> iterator = ids.iterator();
        while (iterator.hasNext()) {
            Integer id = iterator.next();
            AyFaceTask task = getById(id);
            //任务id不正确
            if (Objects.isNull(task)) {
                iterator.remove();
                continue;
            }
            //任务状态为运行中  或者删除状态已删除 不符合条件
            if (TaskStatusEnum.RUNING.getValue() == task.getStatus()
                    ||
                    DeleteStatusEnum.DELETED.getValue() == task.getIsDeleted()) {
                iterator.remove();
            }
        }
        if (ids.isEmpty()) {
            return false;
        }
        return true;
    }

    /**
     * 人脸任务子任务删除前置验证
     *
     * @param id 主任务id
     * @return
     */
    public Boolean deleteSonTaskFrontVerify(Integer id) {
        List<AyFaceTaskSon> ayFaceTaskSons = ayFaceTaskSonService.selectByFaceTaskId(id);
        Iterator<AyFaceTaskSon> sonIterator = ayFaceTaskSons.iterator();
        while (sonIterator.hasNext()) {
            AyFaceTaskSon taskSon = sonIterator.next();
            Integer status = taskSon.getStatus();
            Integer isDeleted = taskSon.getIsDeleted();
            if (Objects.equals(status, TaskStatusEnum.RUNING.getValue()) || Objects.equals(isDeleted, DeleteStatusEnum.DELETED.getValue())) {
                return false;
            }
        }
        return true;
    }

    @Override
    public Boolean deleteTaskByIds(AyTaskIdDto ayTaskIdDto) {
        List<Integer> ids = ayTaskIdDto.getIds();
        //主任务删除验证
        if (!deleteTaskFrontVerify(ids)) {
            return false;
        }
        //子任务删除验证
        List<Integer> verifyIds = ids.stream().filter(id -> deleteSonTaskFrontVerify(id)).collect(Collectors.toList());
        if (verifyIds.isEmpty()) {
            return false;
        }

        deleteTaskWithSonWith(ayTaskIdDto);
        return true;
    }

    @Override
    public Boolean startTaskByIds(AyTaskIdDto ayTaskIdDto) {
        List<Integer> ids = ayTaskIdDto.getIds();
        //主任务验证
        if (!startTaskFrontVerify(ids)) {
            return false;
        }
        //子任务验证
        List<Integer> verifyIds = ids.stream().filter(id -> deleteSonTaskFrontVerify(id)).collect(Collectors.toList());
        if (verifyIds.isEmpty()) {
            return false;
        }
        List<AyFaceTask> ayFaceTasks = this.listByIds(ayTaskIdDto.getIds());
        for (AyFaceTask task : ayFaceTasks) {
            List<AyFaceTaskSon> ayFaceTaskSons = ayFaceTaskSonService.selectByFaceTaskId(task.getId());
            List<TaskRequestDto> taskRequestDtoS = startAyFaceTask(ayTaskIdDto, task, ayFaceTaskSons);
            taskRequestDtoS.stream().forEach(item -> ayFaceTaskSonService.insertFaceTaskSonKafkaOpMsg(item));
        }
        return true;
    }


    @Override
    public Boolean stopTaskByIds(AyTaskIdDto ayTaskIdDto) {
        List<Integer> ids = ayTaskIdDto.getIds();
        //主任务删除验证
        if (!stopTaskFrontVerify(ids)) {
            return false;
        }
        //子任务删除验证
        List<Integer> verifyIds = ids.stream().filter(id -> !stopSonTaskFrontVerify(id)).collect(Collectors.toList());
        if (verifyIds.isEmpty()) {
            return false;
        }

        List<AyFaceTask> ayFaceTasks = this.listByIds(ayTaskIdDto.getIds());
        for (AyFaceTask task : ayFaceTasks) {
            List<AyFaceTaskSon> ayFaceTaskSons = ayFaceTaskSonService.selectByFaceTaskId(task.getId());
            List<String> taskIds = stopAyFaceTask(ayTaskIdDto, task, ayFaceTaskSons);
            taskIds.stream().forEach(item -> ayFaceTaskSonService.deleteFaceTaskSonKafkaOpMsg(item));
        }
        return true;
    }


    private Boolean startTaskFrontVerify(List<Integer> ids) {
        if (ids.isEmpty()) {
            return false;
        }
        Iterator<Integer> iterator = ids.iterator();
        while (iterator.hasNext()) {
            Integer id = iterator.next();
            AyFaceTask task = getById(id);
            //任务id不正确
            if (Objects.isNull(task)) {
                iterator.remove();
                continue;
            }
            //任务状态为运行中  或者删除状态已删除 不符合条件
            if (TaskStatusEnum.RUNING.getValue() == task.getStatus()
                    ||
                    DeleteStatusEnum.DELETED.getValue() == task.getIsDeleted()) {
                iterator.remove();
            }
        }
        if (ids.isEmpty()) {
            return false;
        }
        return true;
    }


    private Boolean stopTaskFrontVerify(List<Integer> ids) {
        if (ids.isEmpty()) {
            return false;
        }
        Iterator<Integer> iterator = ids.iterator();
        while (iterator.hasNext()) {
            Integer id = iterator.next();
            AyFaceTask task = getById(id);
            //任务id不正确
            if (Objects.isNull(task)) {
                iterator.remove();
                continue;
            }
            //任务状态不为运行中  或者删除状态已删除 不符合条件
            if (TaskStatusEnum.RUNING.getValue() != task.getStatus()
                    ||
                    DeleteStatusEnum.DELETED.getValue() == task.getIsDeleted()) {
                iterator.remove();
            }
        }
        if (ids.isEmpty()) {
            return false;
        }
        return true;
    }

    @Override
    public JSONObject taskResultSearch(AyFaceTaskSearchQuery ayFaceTaskSearchQuery, PageQuery pageQuery) {
        String index = IndexUtil.toMonthIndex(IndexNameTypeEnum.AY_FACE.getMessage());
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if (ayFaceTaskSearchQuery.getFaceTaskId() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("faceTaskId", new int[]{ayFaceTaskSearchQuery.getFaceTaskId()}));
        }
        if (ayFaceTaskSearchQuery.getDeviceId() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("deviceId", ayFaceTaskSearchQuery.getDeviceId().split(",")));
        }
        //根据性别查询
        if (ayFaceTaskSearchQuery.getSex() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("genderCode", ayFaceTaskSearchQuery.getSex().split(",")));
        }
        //墨镜
        if (ayFaceTaskSearchQuery.getGlasses() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("glassExtend", ayFaceTaskSearchQuery.getGlasses().split(",")));
        }
        //微笑
        if (ayFaceTaskSearchQuery.getSmile() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("smile", ayFaceTaskSearchQuery.getSmile().split(",")));
        }
        //眼镜
        if (ayFaceTaskSearchQuery.getSunglasses() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("sunGlassExtend", ayFaceTaskSearchQuery.getSunglasses().split(",")));
        }
        //年龄
        if (ayFaceTaskSearchQuery.getAge() != null) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("age", ayFaceTaskSearchQuery.getAge().split(",")));
        }
        if (ayFaceTaskSearchQuery.getStartTime() != null) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("markTime").gte(ayFaceTaskSearchQuery.getStartTime().getTime()));
        }
        if (ayFaceTaskSearchQuery.getEndTime() != null) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("markTime").lte(ayFaceTaskSearchQuery.getEndTime().getTime()));
        }
        try {
            PageResult pageResult = elasticsearchUtil.searchPage(pageQuery, new String[]{index}, boolQueryBuilder);
            return JSON.parseObject(JSON.toJSONString(pageResult));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 结构化任务子任务停止前置验证
     *
     * @param id 主任务id
     * @return
     */
    public Boolean stopSonTaskFrontVerify(Integer id) {
        List<AyFaceTaskSon> ayFaceTaskSons = ayFaceTaskSonService.selectByFaceTaskId(id);
        Iterator<AyFaceTaskSon> sonIterator = ayFaceTaskSons.iterator();
        while (sonIterator.hasNext()) {
            AyFaceTaskSon taskSon = sonIterator.next();
            Integer status = taskSon.getStatus();
            Integer isDeleted = taskSon.getIsDeleted();
            if (Objects.equals(status, TaskStatusEnum.RUNING.getValue()) && Objects.equals(isDeleted, DeleteStatusEnum.NOT_DELETED.getValue())) {
                return false;
            }
        }
        return true;
    }

}
